home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers3.zip / DEPCA.ASM < prev    next >
Assembly Source File  |  1992-03-02  |  21KB  |  863 lines

  1. version    equ    2
  2.  
  3. ;  Copyright, 1991-1992, Russell Nelson, Crynwr Software
  4.  
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation, version 1.
  8. ;
  9. ;   This program is distributed in the hope that it will be useful,
  10. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ;   GNU General Public License for more details.
  13. ;
  14. ;   You should have received a copy of the GNU General Public License
  15. ;   along with this program; if not, write to the Free Software
  16. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.     include    defs.asm
  19.  
  20. NI_CSR        equ    0
  21. RBI        equ    2
  22. DATA_REG    equ    4
  23. ADDR_REG    equ    6
  24.     CSR0        equ    0
  25.     CSR1        equ    1
  26.     CSR2        equ    2
  27.     CSR3        equ    3
  28. EBASE        equ    0ch
  29.  
  30. NI_CSR_VALUE    equ    8ah
  31.  
  32. outport    macro    reg
  33.     push    ax
  34.     setport    ADDR_REG
  35.     mov    ax,reg
  36.     out    dx,ax
  37.     in    ax,dx            ;always follow a write by a read
  38.  
  39.     setport    DATA_REG
  40.     pop    ax
  41.     out    dx,ax
  42.     in    ax,dx            ;always follow a write by a read
  43.  
  44.     endm
  45.  
  46.  
  47. ;
  48. ;     Control and Status Register 0 (CSR0) bit definitions
  49. ;
  50. CSR0_ERR    equ     8000h    ; Error summary
  51. CSR0_BABL    equ     4000h    ; Babble transmitter timeout error
  52. CSR0_CERR    equ    2000h    ; Collision Error
  53. CSR0_MISS    equ    1000h    ; Missed packet
  54. CSR0_MERR    equ    0800h    ; Memory Error
  55. CSR0_RINT    equ    0400h    ; Reciever Interrupt
  56. CSR0_TINT       equ    0200h    ; Transmit Interrupt
  57. CSR0_IDON    equ    0100h    ; Initialization Done
  58. CSR0_INTR    equ    0080h    ; Interrupt Flag
  59. CSR0_INEA    equ    0040h    ; Interrupt Enable
  60. CSR0_RXON    equ    0020h    ; Receiver on
  61. CSR0_TXON    equ    0010h   ; Transmitter on
  62. CSR0_TDMD    equ    0008h    ; Transmit Demand
  63. CSR0_STOP    equ    0004h     ; Stop
  64. CSR0_STRT    equ    0002h    ; Start
  65. CSR0_INIT    equ    0001h    ; Initialize
  66.  
  67. ;
  68. ;     Initialization Block  Mode operation Bit Definitions.
  69. ;
  70. M_PROM        equ    8000h    ; Promiscuous Mode
  71. M_INTL        equ    0040h   ; Internal Loopback
  72. M_DRTY        equ    0020h   ; Disable Retry
  73. M_COLL        equ    0010h    ; Force Collision
  74. M_DTCR        equ    0008h    ; Disable Transmit CRC)
  75. M_LOOP        equ    0004h    ; Loopback
  76. M_DTX        equ    0002h    ; Disable the Transmitter
  77. M_DRX        equ    0001h   ; Disable the Reciever
  78.  
  79.  
  80. ;
  81. ;     Receive message descriptor bit definitions.
  82. ;
  83. RCV_OWN        equ    8000h    ; owner bit 0 = host, 1 = lance
  84. RCV_ERR        equ    4000h    ; Error Summary
  85. RCV_FRAM    equ     2000h    ; Framing Error
  86. RCV_OFLO    equ    1000h    ; Overflow Error
  87. RCV_CRC        equ    0800h    ; CRC Error
  88. RCV_BUF_ERR    equ     0400h    ; Buffer Error
  89. RCV_START    equ    0200h    ; Start of Packet
  90. RCV_END        equ    0100h    ; End of Packet
  91.  
  92.  
  93. ;
  94. ;    Transmit  message descriptor bit definitions.
  95. ;
  96. XMIT_OWN    equ    8000h    ; owner bit 0 = host, 1 = lance
  97. XMIT_ERR    equ    4000h   ; Error Summary
  98. XMIT_RETRY    equ    1000h   ; more the 1 retry needed to Xmit
  99. XMIT_1_RETRY    equ    0800h    ; one retry needed to Xmit
  100. XMIT_DEF    equ    0400h    ; Deferred
  101. XMIT_START    equ    0200h    ; Start of Packet
  102. XMIT_END    equ    0100h    ; End of Packet
  103.  
  104. ;
  105. ;    Miscellaneous Equates
  106. ;
  107.  
  108. TRANSMIT_BUF_COUNT    equ    1
  109. RECEIVE_BUF_COUNT    equ    8
  110. TRANSMIT_BUF_SIZE    equ    1518
  111. RECEIVE_BUF_SIZE    equ    1518
  112.  
  113. ;
  114. ;    Receive Message Descriptor
  115. ;
  116. rcv_msg_dscp struc
  117.     rmd0    dw    ?    ; Rec. Buffer Lo-Address
  118.     rmd1    dw    ?    ; Status bits / Hi-Address
  119.     rmd2    dw    ?    ; Buff Byte-length (2's Comp)
  120.     rmd3    dw    ?    ; Receive message length
  121. rcv_msg_dscp ends
  122.  
  123.  
  124. ;
  125. ;    Transmit Message Descriptor
  126. ;
  127. xmit_msg_dscp struc
  128.     tmd0    dw    ?    ; Xmit Buffer Lo-Address
  129.     tmd1    dw    ?    ; Status bits / Hi-Address
  130.     tmd2     dw    ?    ; Buff Byte-length (2's Comp)
  131.     tmd3    dw    ?    ; Buffer Status bits & TDR value
  132. xmit_msg_dscp ends
  133.  
  134. lance_seg    segment at 0
  135.  
  136. ;
  137. ;the LANCE requires that the descriptor pointers be on a qword boundary.
  138. ;
  139.     align    8
  140.  
  141. transmit_dscps    xmit_msg_dscp    TRANSMIT_BUF_COUNT dup(<>)
  142. receive_dscps    rcv_msg_dscp    RECEIVE_BUF_COUNT dup(<>)
  143.  
  144. ;
  145. ;      LANCE Initialization Block
  146. ;
  147.     align    2
  148. init_block        label    byte
  149. init_mode        dw    0
  150. init_addr        db    EADDR_LEN dup(?)    ; Our Ethernet address
  151. init_filter        db    8 dup(0)    ;Multicast filter.
  152. init_receive        dw    ?,?        ;Receive Ring Pointer.
  153. init_transmit          dw    ?,?          ;Transmit Ring Pointer.
  154.  
  155. transmit_bufs    equ    $
  156. receive_bufs    equ    transmit_bufs + TRANSMIT_BUF_COUNT * TRANSMIT_BUF_SIZE
  157.  
  158. lance_seg    ends
  159.  
  160. code    segment    para public
  161.     assume    cs:code, ds:code
  162.  
  163.         public    int_no
  164. int_no        db    2,0,0,0            ;must be four bytes long for get_number.
  165. io_addr        dw    -1,-1
  166. base_addr    dw    -1,-1
  167.  
  168.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  169. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  170. driver_type    db    66        ;from the packet spec
  171. driver_name    db    'DEPCA',0    ;name of the driver.
  172. driver_function    db    2        ;basic, extended
  173. parameter_list    label    byte
  174.     db    1    ;major rev of packet driver
  175.     db    9    ;minor rev of packet driver
  176.     db    14    ;length of parameter list
  177.     db    EADDR_LEN    ;length of MAC-layer address
  178.     dw    GIANT    ;MTU, including MAC headers
  179.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  180.     dw    RECEIVE_BUF_COUNT-1    ;(# of back-to-back MTU rcvs) - 1
  181.     dw    TRANSMIT_BUF_COUNT-1    ;(# of successive xmits) - 1
  182. int_num    dw    0    ;Interrupt # to hook for post-EOI
  183.             ;processing, 0 == none,
  184.  
  185.     public    rcv_modes
  186. rcv_modes    dw    7        ;number of receive modes in our table.
  187.         dw    0               ;There is no mode zero
  188.         dw    0        ;none at all.
  189.         dw    0        ;only ours.
  190.         dw    rcv_mode_3    ;ours plus broadcast
  191.         dw    0        ;some multicasts
  192.         dw    0        ;all multicasts
  193.         dw    rcv_mode_6    ;all packets
  194.  
  195. save_csr1    dw    ?
  196. save_csr2    dw    ?
  197.  
  198. transmit_head    dw    transmit_dscps    ;->next packet to be filled by host.
  199. receive_head    dw    receive_dscps    ;->next packet to be filled by LANCE.
  200.  
  201.     public    as_send_pkt
  202. ; The Asynchronous Transmit Packet routine.
  203. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  204. ;   interrupts possibly enabled.
  205. ; Exit with nc if ok, or else cy if error, dh set to error number.
  206. ;   es:di and interrupt enable flag preserved on exit.
  207. as_send_pkt:
  208.     ret
  209.  
  210.     public    drop_pkt
  211. ; Drop a packet from the queue.
  212. ; Enter with es:di -> iocb.
  213. drop_pkt:
  214.     assume    ds:nothing
  215.     ret
  216.  
  217.     public    xmit
  218. ; Process a transmit interrupt with the least possible latency to achieve
  219. ;   back-to-back packet transmissions.
  220. ; May only use ax and dx.
  221. xmit:
  222.     assume    ds:nothing
  223.     ret
  224.  
  225.  
  226.     public    send_pkt
  227. send_pkt:
  228. ;enter with ds:si -> packet, cx = packet length.
  229. ;exit with nc if ok, or else cy if error, dh set to error number.
  230.     assume    ds:nothing
  231.     mov    es,base_addr
  232.     assume    es:lance_seg
  233.  
  234.     xor    bx,bx
  235.  
  236.     mov    ax,18
  237.     call    set_timeout
  238. send_pkt_1:
  239.     test    transmit_dscps[bx].tmd1,XMIT_OWN    ;Did the lance chip give it back?
  240.     je    send_pkt_2
  241.     call    do_timeout
  242.     jne    send_pkt_1
  243.     mov    dh,CANT_SEND
  244.     stc
  245.     ret
  246. send_pkt_2:
  247. ;reset error indications.
  248.     and    transmit_dscps[bx].tmd1,not (XMIT_ERR or XMIT_DEF or XMIT_1_RETRY or XMIT_RETRY)    ;Did the lance chip give it back?
  249.     mov    transmit_dscps[bx].tmd3,0    ;reset all error bits.
  250.  
  251.     mov    ax,cx            ;store the count.
  252.     cmp    ax,RUNT            ; minimum length for Ether
  253.     ja    oklen
  254.     mov    ax,RUNT            ; make sure size at least RUNT
  255. oklen:
  256.     neg    ax
  257.     mov    transmit_dscps[bx].tmd2,ax    ;store the negative of the cnt.
  258.  
  259.     mov    ax,transmit_dscps[bx].tmd0    ;store the packet.
  260.     mov    dx,transmit_dscps[bx].tmd1
  261.     call    phys_to_segmoffs
  262.     assume    es:nothing
  263.     rep    movsb
  264.  
  265.     mov    es,base_addr
  266.     assume    es:lance_seg
  267.     or    transmit_dscps[bx].tmd1,XMIT_OWN    ;give it to the lance chip.
  268.  
  269. ;Inform LANCE that it should poll for a packet.
  270.     loadport
  271.     mov    ax,CSR0_INEA or CSR0_TDMD
  272.     outport    CSR0
  273.     clc
  274.     ret
  275.  
  276.  
  277. detect_board:
  278. ;test to see if a board is located at io_addr.
  279. ;setup to read first byte of ethernet address rom when successful.
  280. ;return nz if not.
  281.     assume    cs:code, ds:code
  282.  
  283.     loadport
  284.     setport    NI_CSR            ;enable the rev. E DEPCA card.
  285.     mov    al,8
  286.     out    dx,al
  287.     setport    EBASE            ;is it in this port?
  288.     call    detect_port
  289.     je    detect_board_1        ;yup!
  290.     setport    EBASE+1            ;look on the next port for rev. E
  291.     call    detect_port
  292. detect_board_1:
  293.     pushf                ;preserve the result.
  294.     loadport
  295.     setport    NI_CSR            ;restore the NI_CSR contents.
  296.     mov    al,NI_CSR_VALUE
  297.     out    dx,al
  298.     popf
  299.     ret
  300.  
  301.  
  302. depca_pattern    db    0FFh, 00h, 55h, 0AAh, 0FFh, 00h, 55h, 0AAh
  303.  
  304. detect_port:
  305. ;enter with dx = port to read from, looking for depca_pattern.
  306. ;exit with zr if we found it, nz if not.
  307.     mov    cx,32+8            ;do 32 reps, plus look at 8 to match.
  308.     mov    di,0            ;start at the beginning of the string.
  309. detect_port_1:
  310.     in    al,dx            ;input byte.
  311.     cmp    al,depca_pattern[di]    ;do they match?
  312.     jne    detect_port_2        ;no, try again.
  313.     inc    di            ;yes, look at another character.
  314.     cmp    di, 8            ;need to match eight chars.
  315.     jne    short detect_port_3
  316.     ret
  317. detect_port_2:
  318.     xor    di,di            ;start at the beginning of the pattern.
  319. detect_port_3:
  320.     loop    detect_port_1
  321.     or    sp,sp            ;return nz.
  322.     ret
  323.  
  324.  
  325.     public    get_address
  326. get_address:
  327. ;get the address of the interface.
  328. ;enter with es:di -> place to get the address, cx = size of address buffer.
  329. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  330.     assume    ds:code, es:nothing
  331.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  332.     jb    get_address_2
  333.     push    di
  334.     call    detect_board
  335.     pop    di
  336.     mov    cx,EADDR_LEN
  337.     loadport            ; Get our Ethernet address base.
  338.     setport    EBASE
  339.     cld
  340. get_address_1:
  341.     in    al,dx            ; get a byte of the eprom address
  342.     stosb
  343.     loop    get_address_1        ; go back for rest
  344.     mov    cx,EADDR_LEN
  345.     clc
  346.     ret
  347. get_address_2:
  348.     stc
  349.     ret
  350.  
  351.  
  352.     public    set_address
  353. set_address:
  354. ;enter with ds:si -> Ethernet address, CX = length of address.
  355. ;exit with nc if okay, or cy, dh=error if any errors.
  356.     assume    ds:nothing
  357.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  358.     je    set_address_4
  359.     mov    dh,BAD_ADDRESS
  360.     stc
  361.     jmp    short set_address_done
  362. set_address_4:
  363.  
  364.     mov    es,base_addr
  365.     mov    di,offset init_addr
  366.     rep    movsb
  367.     call    initialize        ;initialize with our new address.
  368.  
  369. set_address_okay:
  370.     mov    cx,EADDR_LEN        ;return their address length.
  371.     clc
  372. set_address_done:
  373.     push    cs
  374.     pop    ds
  375.     assume    ds:code
  376.     ret
  377.  
  378.  
  379. rcv_mode_1:
  380.     mov    ax,M_DRX or M_DTX    ;disable the receiver and transmitter.
  381.     jmp    initialize_nomulti
  382. rcv_mode_3:
  383.     xor    ax,ax            ;don't accept any multicast frames.
  384.     call    initialize_multi
  385.     mov    ax,0            ;non-promiscuous mode
  386.     jmp    short initialize_nomulti
  387. rcv_mode_5:
  388.     mov    ax,-1            ;accept any multicast frames.
  389.     call    initialize_multi
  390.     mov    ax,0            ;non-promiscuous mode
  391.     jmp    short initialize_nomulti
  392. rcv_mode_6:
  393.     mov    ax,M_PROM    ;promiscuous mode
  394. initialize_nomulti:
  395.     mov    es,base_addr
  396.     mov    es:init_mode,ax
  397.  
  398. initialize:
  399.     loadport
  400.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  401.     outport    CSR0
  402.  
  403.     mov    ax,2            ;write the bus config register.
  404.     outport    CSR3
  405.  
  406.     mov    ax,save_csr1        ;write the low word.
  407.     outport    CSR1
  408.  
  409.     mov    ax,save_csr2        ;write the high word.
  410.     outport    CSR2
  411.  
  412.     mov    ax,CSR0_INEA or CSR0_STRT or CSR0_INIT    ;reinit and restart.
  413.     outport    CSR0
  414.  
  415.     setport    DATA_REG
  416.  
  417.     mov    ax,36            ;wait one second for the board
  418.     call    set_timeout        ;  to timeout.
  419. initialize_1:
  420.     in    ax,dx
  421.     test    ax,CSR0_IDON
  422.     jne    initialize_2
  423.     call    do_timeout
  424.     jne    initialize_1
  425.     stc
  426.     ret
  427. initialize_2:
  428.     clc
  429.     ret
  430.  
  431.  
  432. initialize_multi:
  433. ;enter with ax = value for all multicast hash bits.
  434.     mov    es,base_addr
  435.     mov    di,offset init_filter
  436.     mov    cx,8/2
  437.     rep    stosw
  438.     ret
  439.  
  440.  
  441.     public    set_multicast_list
  442. set_multicast_list:
  443. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  444. ;return nc if we set all of them, or cy,dh=error if we didn't.
  445.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  446.     stc
  447.     ret
  448.  
  449.  
  450.     public    terminate
  451. terminate:
  452.     call    rcv_mode_1        ;don't receive any apckets.
  453.  
  454.     ret
  455.  
  456.     public    reset_interface
  457. reset_interface:
  458. ;reset the interface.
  459.     assume    ds:code
  460.     ret
  461.  
  462.  
  463. ;called when we want to determine what to do with a received packet.
  464. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  465.     extrn    recv_find: near
  466.  
  467. ;called after we have copied the packet into the buffer.
  468. ;enter with ds:si ->the packet, cx = length of the packet.
  469.     extrn    recv_copy: near
  470.  
  471.     extrn    count_in_err: near
  472.     extrn    count_out_err: near
  473.  
  474. LANCE_ISR_ACKNOWLEDGE equ (CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  475.  
  476.     public    recv
  477. recv:
  478. ;called from the recv isr.  All registers have been saved, and ds=cs.
  479. ;Upon exit, the interrupt will be acknowledged.
  480.     assume    ds:code
  481.  
  482.     loadport
  483.     setport    ADDR_REG
  484.     mov    ax,CSR0
  485.     out    dx,ax
  486.     in    ax,dx
  487.     setport    DATA_REG
  488.     in    ax,dx
  489.     mov    bx,ax            ;make a copy.
  490.  
  491. ; Acknowledge the Interrupt from the controller, but disable further
  492. ; controller Interrupts until we service the current interrupt.
  493. ;
  494. ;(CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  495. ;
  496.     and    ax,not LANCE_ISR_ACKNOWLEDGE
  497.     out    dx,ax
  498.     in    ax,dx        ; follow all writes by a read
  499.  
  500.     test    bx,CSR0_RINT        ;receive interrupt?
  501.     jne    recv_RINT        ;yes.
  502.     jmp    recv_done        ;no, we're done.
  503. recv_RINT:
  504.  
  505.     mov    es,base_addr
  506.     assume    es:lance_seg
  507.     mov    bx,receive_head
  508.  
  509. recv_search:
  510.     test    lance_seg:[bx].rmd1,RCV_OWN    ;do we own this buffer?
  511.     je    recv_own        ;yes - process it.
  512.     call    inc_recv_ring        ;go to the next one.
  513.     cmp    bx,receive_head        ;did we get back to the beginning?
  514.     jne    recv_search        ;not yet.
  515.     jmp    recv_done        ;yes -- spurious interrupt!
  516. recv_own:
  517.     test    lance_seg:[bx].rmd1,RCV_ERR    ;Any errors in this buffer?
  518.     jne    recv_err        ;yes -- ignore this packet.
  519.  
  520.     mov    cx,lance_seg:[bx].rmd3
  521.     and    cx,0fffh        ;strip off the reserved bits
  522.  
  523.     mov    ax,lance_seg:[bx].rmd0    ;fetch the packet.
  524.     mov    dx,lance_seg:[bx].rmd1
  525.     call    phys_to_segmoffs
  526.     assume    es:nothing
  527.  
  528.     push    es
  529.     push    di
  530.     push    bx
  531.  
  532.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  533.                     ;  point to the packet type.
  534.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  535.     mov    ax, es:[di]
  536.     xchg    ah, al
  537.     cmp     ax, 1500
  538.     ja    BlueBookPacket
  539.     inc    di            ;set di to 802.2 header
  540.     inc    di
  541.     mov    dl, IEEE8023
  542. BlueBookPacket:
  543.     push    cx
  544.     call    recv_find
  545.     pop    cx
  546.  
  547.     pop    bx
  548.     pop    si
  549.     pop    ds
  550.     assume    ds:nothing, es:nothing
  551.  
  552.     mov    ax,es            ;is this pointer null?
  553.     or    ax,di
  554.     je    recv_free        ;yes - just free the frame.
  555.  
  556.     push    es
  557.     push    di
  558.     push    cx
  559.     rep    movsb
  560.     pop    cx
  561.     pop    si
  562.     pop    ds
  563.     assume    ds:nothing
  564.  
  565.     call    recv_copy
  566.  
  567.     jmp    short recv_free
  568.  
  569. recv_err:
  570.     call    count_in_err
  571. recv_free:
  572.     push    cs
  573.     pop    ds
  574.     assume    ds:code
  575.     mov    es,base_addr
  576.     assume    es:lance_seg
  577.  
  578. ;clear any error bits.
  579.     and    lance_seg:[bx].rmd1,not (RCV_ERR or RCV_FRAM or RCV_OFLO or RCV_CRC or RCV_BUF_ERR)
  580.     or    lance_seg:[bx].rmd1,RCV_OWN    ;give it back to the lance.
  581.     call    inc_recv_ring            ;go to the next one.
  582.     test    lance_seg:[bx].rmd1,RCV_OWN    ;Do we own this one?
  583.     je    recv_own
  584.     mov    receive_head,bx        ;remember where the next one starts.
  585. recv_done:
  586.     loadport            ;enable interrupts again.
  587.     setport    DATA_REG
  588.     mov    ax,CSR0_INEA
  589.     out    dx,ax
  590.  
  591.     ret
  592.  
  593.  
  594. inc_recv_ring:
  595. ;advance bx to the next receive ring descriptor.
  596.     assume    ds:nothing
  597.     add    bx,(size rcv_msg_dscp)
  598.     cmp    bx,offset receive_dscps + RECEIVE_BUF_COUNT * (size rcv_msg_dscp)
  599.     jb    inc_recv_ring_1
  600.     mov    bx,offset receive_dscps
  601. inc_recv_ring_1:
  602.     ret
  603.  
  604.  
  605.     public    recv_exiting
  606. recv_exiting:
  607. ;called from the recv isr after interrupts have been acknowledged.
  608. ;Only ds and ax have been saved.
  609.     assume    ds:nothing
  610.     ret
  611.  
  612.  
  613. phys_to_segmoffs:
  614. ;enter with dx:ax as the physical address of the buffer,
  615. ;exit with es:di -> buffer.
  616.     assume    ds:nothing
  617.   if 0
  618.     shl    dx,16-4            ;move the upper four bits into position.
  619.     mov    di,ax            ;now get the low 12 bits of the segment.
  620.     shr    di,4
  621.     or    dx,di            ;combine them.
  622.     mov    es,dx
  623.     mov    di,ax
  624.     and    di,0fh            ;now compute the offset.
  625.   else
  626.     mov    es,base_addr
  627.     mov    di,ax
  628.   endif
  629.     ret
  630.  
  631.     include    timeout.asm
  632.  
  633. end_resident    label    byte
  634.  
  635.  
  636.     public    usage_msg
  637. usage_msg    db    "usage: depca [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr> <mem_addr>",CR,LF,'$'
  638. no_board_msg    db    "No DEPCA detected.",CR,LF,'$'
  639. io_addr_funny_msg    label    byte
  640.         db    "No DEPCA detected, continuing anyway.",CR,LF,'$'
  641. bad_reset_msg    db    "Unable to reset the DEPCA.",CR,LF,'$'
  642. bad_init_msg    db    "Unable to initialize the DEPCA.",CR,LF,'$'
  643.  
  644.     public    copyright_msg
  645. copyright_msg    db    "Packet driver for a Digital Equipment Corporation DEPCA, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  646.         db    '$'
  647.  
  648. int_no_name    db    "Interrupt number ",'$'
  649. io_addr_name    db    "I/O port ",'$'
  650. base_addr_name    db    "Memory address ",'$'
  651.  
  652.     extrn    set_recv_isr: near
  653.     extrn    maskint: near
  654.  
  655. ;enter with si -> argument string, di -> dword to store.
  656. ;if there is no number, don't change the number.
  657.     extrn    get_number: near
  658.  
  659. ;enter with dx -> name of word, di -> dword to print.
  660.     extrn    print_number: near
  661.  
  662.     public    parse_args
  663. parse_args:
  664. ;exit with nc if all went well, cy otherwise.
  665.     assume    ds:code
  666.     mov    di,offset int_no
  667.     call    get_number
  668.     mov    di,offset io_addr
  669.     call    get_number
  670.     mov    di,offset base_addr
  671.     call    get_number
  672.     clc
  673.     ret
  674.  
  675.  
  676.     public    etopen
  677. etopen:
  678.     assume    ds:code
  679.  
  680.     cmp    io_addr,-1        ;Did they ask for auto-detect?
  681.     je    find_board
  682.  
  683.     call    detect_board        ;no, just verify its existance.
  684.     je    find_board_found
  685.  
  686.     mov    dx,offset io_addr_funny_msg
  687.     mov    ah,9
  688.     int    21h
  689.  
  690.     jmp    find_board_found
  691.  
  692. find_board:
  693.     mov    io_addr,300h        ;Search for the Ethernet address at 300h
  694.     mov    io_addr+2,0
  695.     call    detect_board
  696.     je    find_board_found
  697.     mov    io_addr,200h        ;Search at 200h
  698.     call    detect_board
  699.     je    find_board_found
  700.  
  701.     mov    dx,offset no_board_msg    ;Tell them that we can't find it.
  702.     mov    ah,9
  703.     int    21h
  704.  
  705.     stc
  706.     ret
  707. find_board_found:
  708.  
  709.     mov    al, int_no        ; Get board's interrupt vector
  710.     add    al, 8
  711.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  712.     jb    set_int_num        ; No.
  713.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  714. set_int_num:
  715.     xor    ah, ah            ; Clear high byte
  716.     mov    int_num, ax        ; Set parameter_list int num.
  717.  
  718.     mov    al,int_no
  719.     call    maskint            ;disable these interrupts.
  720.  
  721.     loadport
  722.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  723.     outport    CSR0
  724.  
  725. ;set up transmit descriptor ring.
  726.     mov    es,base_addr
  727.     assume    es:lance_seg
  728.     mov    cx,TRANSMIT_BUF_COUNT
  729.     mov    bx,offset transmit_dscps
  730.     mov    di,offset transmit_bufs
  731. setup_transmit:
  732.     call    segmoffs_to_phys
  733.  
  734.     or    dx,XMIT_START or XMIT_END
  735.     mov    lance_seg:[bx].tmd0,ax        ;points to the buffer.
  736.     mov    lance_seg:[bx].tmd1,dx
  737.  
  738.     add    bx,(size xmit_msg_dscp)
  739.     add    di,TRANSMIT_BUF_SIZE
  740.     loop    setup_transmit
  741.  
  742. ;set up receive descriptor ring.
  743.     mov    cx,RECEIVE_BUF_COUNT
  744.     mov    bx,offset receive_dscps
  745.     mov    di,offset receive_bufs
  746. setup_receive:
  747.     call    segmoffs_to_phys
  748.  
  749.     or    dx,RCV_OWN
  750.     mov    lance_seg:[bx].rmd0,ax        ;points to the buffer.
  751.     mov    lance_seg:[bx].rmd1,dx
  752.  
  753.     mov    lance_seg:[bx].rmd2,-RECEIVE_BUF_SIZE
  754.     mov    lance_seg:[bx].rmd3,0
  755.  
  756.     add    bx,(size rcv_msg_dscp)
  757.     add    di,RECEIVE_BUF_SIZE
  758.     loop    setup_receive
  759.  
  760. ;initialize the board.
  761.     mov    cx,EADDR_LEN        ;get our address.
  762.     mov    di,offset init_addr
  763.     call    get_address
  764.  
  765.     mov    cx,RECEIVE_BUF_COUNT
  766.     call    compute_log2
  767.  
  768.     mov    di,offset receive_dscps
  769.     call    segmoffs_to_phys
  770.     or    dx,cx            ;include the buffer size bits.
  771.     mov    init_receive[0],ax
  772.     mov    init_receive[2],dx
  773.  
  774.     mov    cx,TRANSMIT_BUF_COUNT
  775.     call    compute_log2
  776.  
  777.     mov    di,offset transmit_dscps
  778.     call    segmoffs_to_phys
  779.     or    dx,cx            ;include the buffer size bits.
  780.     mov    init_transmit[0],ax
  781.     mov    init_transmit[2],dx
  782.  
  783.     mov    di,offset init_block    ;now tell the board where the init
  784.     call    segmoffs_to_phys    ;  block is.
  785.     mov    save_csr1,ax
  786.     mov    save_csr2,dx
  787.  
  788.     call    rcv_mode_3
  789.     jnc    init_ok
  790.  
  791.     mov    dx,offset bad_init_msg
  792.     mov    ah,9
  793.     int    21h
  794.  
  795.     stc
  796.     ret
  797.  
  798. init_ok:
  799. ;
  800. ; Now hook in our interrupt
  801. ;
  802.     call    set_recv_isr
  803.  
  804.     loadport
  805.     setport    NI_CSR
  806.     mov    al,NI_CSR_VALUE        ;disable ROM, enable rev. E DEPCA,
  807.                     ;  enable the interrupt line,
  808.     out    dx,al
  809.  
  810.     mov    dx,offset end_resident
  811.     clc
  812.     ret
  813.  
  814.     public    print_parameters
  815. print_parameters:
  816. ;echo our command-line parameters
  817.     mov    di,offset int_no
  818.     mov    dx,offset int_no_name
  819.     call    print_number
  820.     mov    di,offset io_addr
  821.     mov    dx,offset io_addr_name
  822.     call    print_number
  823.     mov    di,offset base_addr
  824.     mov    dx,offset base_addr_name
  825.     call    print_number
  826.     ret
  827.  
  828. compute_log2:
  829. ;enter with cx = number of buffers.
  830. ;exit with cx = log2(number of buffers) << 13.
  831.     mov    ax,-1
  832. compute_log2_1:
  833.     inc    ax
  834.     shr    cx,1
  835.     jne    compute_log2_1
  836.     mov    cl,13
  837.     shl    ax,cl
  838.     mov    cx,ax
  839.     ret
  840.  
  841.  
  842. segmoffs_to_phys:
  843. ;enter with es:di -> buffer.
  844. ;exit with dx:ax as the physical address of the buffer,
  845.  
  846.   if 0    ; The DEPCA doesn't use system memory, it uses its own.
  847.     mov    dx,es            ;get the high 4 bits of the segment,
  848.     shr    dx,16-4
  849.     mov    ax,es            ;and the low 12 bits of the segment.
  850.     shl    ax,4
  851.     add    ax,di            ;add in the offset.
  852.     adc    dx,0
  853.   else
  854.     xor    dx,dx            ;the offset is the only part of the
  855.     mov    ax,di            ;  address.
  856.   endif
  857.     ret
  858.  
  859.  
  860. code    ends
  861.  
  862.     end
  863.